package com.sandwormz.webcompiler;

import java.util.List;

import org.apache.commons.cli.CommandLine;
import org.apache.commons.cli.HelpFormatter;
import org.apache.commons.cli.OptionBuilder;
import org.apache.commons.cli.Options;
import org.apache.commons.cli.PosixParser;
import org.apache.log4j.Level;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * The command line utility for running the compiler.
 * 
 * @author mbryant
 * 
 */
public class CompilerCLI {

    private static final Logger _logger = LoggerFactory
            .getLogger(CompilerCLI.class);

    /**
     * Typically this will be run with a single arg: the location of the page to compile.
     * 
     * @param args the cli args
     */
    public static void main(final String[] args) {

        PosixParser parser = new PosixParser();
        try {
            CommandLine cmd = parser.parse(createOptions(), args);
            String[] extraArgs = cmd.getArgs();

            String htmlPath = cmd.getOptionValue('p');
            if (htmlPath == null) {
                if (extraArgs.length == 0) {
                    printCliHelp("missing path");
                    return;
                }
                htmlPath = extraArgs[0];
            }

            if (cmd.hasOption("veryverbose")) {
                org.apache.log4j.Logger.getRootLogger().setLevel(Level.ALL);
            } else if (cmd.hasOption("verbose")) {
                org.apache.log4j.Logger.getRootLogger().setLevel(Level.DEBUG);
            } else {
                org.apache.log4j.Logger.getRootLogger().setLevel(Level.INFO);
            }

            try {
                ResourceWithContents sourceFile =
                        ResourceWithContents.Builder().path(htmlPath).build();
                Page pageToCompile = new Page(sourceFile);
                List<ResourceWithContents> compilationUnits =
                        pageToCompile.compile();
                pageToCompile.writeFiles(compilationUnits);

            } catch (PageCompilerException e) {
                _logger.debug("Failed to compile", e);
                if (e.getLine() > -1) {
                    _logger.error("Error at line " + e.getLine() + ": "
                            + e.getMessage());
                } else {
                    _logger.error("Error at unknown line: " + e.getMessage());
                }
            } catch (PageCompilerError e) {
                _logger.debug("Failed to compile", e);
                if (e.getLine() > -1) {
                    _logger.error("Error at line " + e.getLine() + ": "
                            + e.getMessage());
                } else {
                    _logger.error("Error at unknown line: " + e.getMessage());
                }
            } catch (IllegalStateException e) {
                _logger.error("Error: " + e.getLocalizedMessage());
            }

        } catch (org.apache.commons.cli.ParseException e) {
            printCliHelp("Error in parsing arguments:\n" + e.getMessage());
        } catch (Exception e) {// Catch exception if any
            e.printStackTrace();
            printCliHelp("Unexpected Error: " + e.getClass().getCanonicalName()
                    + " " + e.getMessage());
        }

        System.exit(0);
    }

    private static Options createOptions() {
        Options mOptions = new Options();

        OptionBuilder.withArgName("string");
        OptionBuilder.hasArg(true);
        OptionBuilder.withDescription("path of the html file to compile");
        OptionBuilder.isRequired(false);
        OptionBuilder.withLongOpt("path");
        mOptions.addOption(OptionBuilder.create('p'));

        OptionBuilder.hasArg(false);
        OptionBuilder.withDescription("print lots of debug messages");
        OptionBuilder.isRequired(false);
        OptionBuilder.withLongOpt("verbose");
        mOptions.addOption(OptionBuilder.create('v'));

        OptionBuilder.hasArg(false);
        OptionBuilder.withDescription("print lots and lots of debug messages");
        OptionBuilder.isRequired(false);
        OptionBuilder.withLongOpt("veryverbose");
        mOptions.addOption(OptionBuilder.create('V'));

        return mOptions;
    }

    /*
     * private method to output the command line options help
     */
    private static void printCliHelp(final String message) {
        System.out.println(message);
        HelpFormatter formatter = new HelpFormatter();
        formatter.printHelp("closurecli [-p path] [path] \n", createOptions());
        System.exit(-1);
    }

}
